/**
 * 统一响应格式工具
 */

"use strict";

const { HTTP_STATUS, createError } = require("../constants/errorCodes");

/**
 * 标准响应结构
 * @typedef {Object} StandardResponse
 * @property {number} code - 业务状态码
 * @property {string} message - 响应消息
 * @property {any} data - 响应数据
 * @property {Object} meta - 元数据（分页、统计等）
 * @property {string} timestamp - 时间戳
 * @property {string} requestId - 请求ID
 */

/**
 * 分页元数据结构
 * @typedef {Object} PaginationMeta
 * @property {number} page - 当前页码
 * @property {number} pageSize - 每页数量
 * @property {number} total - 总数量
 * @property {number} totalPages - 总页数
 * @property {boolean} hasNext - 是否有下一页
 * @property {boolean} hasPrev - 是否有上一页
 */

/**
 * 创建成功响应
 * @param {any} data - 响应数据
 * @param {string} message - 成功消息
 * @param {Object} meta - 元数据
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function success(data = null, message = "Success", meta = null, requestId = null) {
  return {
    code: HTTP_STATUS.OK,
    message,
    data,
    meta,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建创建成功响应
 * @param {any} data - 创建的数据
 * @param {string} message - 成功消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function created(data = null, message = "Created successfully", requestId = null) {
  return {
    code: HTTP_STATUS.CREATED,
    message,
    data,
    meta: null,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建更新成功响应
 * @param {any} data - 更新的数据
 * @param {string} message - 成功消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function updated(data = null, message = "Updated successfully", requestId = null) {
  return {
    code: HTTP_STATUS.OK,
    message,
    data,
    meta: null,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建删除成功响应
 * @param {string} message - 成功消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function deleted(message = "Deleted successfully", requestId = null) {
  return {
    code: HTTP_STATUS.OK,
    message,
    data: null,
    meta: null,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建分页响应
 * @param {Array} items - 数据项数组
 * @param {number} page - 当前页码
 * @param {number} pageSize - 每页数量
 * @param {number} total - 总数量
 * @param {string} message - 响应消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function paginated(items, page, pageSize, total, message = "Success", requestId = null) {
  const totalPages = Math.ceil(total / pageSize);
  const hasNext = page < totalPages;
  const hasPrev = page > 1;

  const meta = {
    pagination: {
      page: parseInt(page),
      pageSize: parseInt(pageSize),
      total: parseInt(total),
      totalPages,
      hasNext,
      hasPrev
    }
  };

  return {
    code: HTTP_STATUS.OK,
    message,
    data: items,
    meta,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建列表响应（不分页）
 * @param {Array} items - 数据项数组
 * @param {number} total - 总数量（可选）
 * @param {string} message - 响应消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function list(items, total = null, message = "Success", requestId = null) {
  const meta = total !== null ? { total: parseInt(total) } : null;

  return {
    code: HTTP_STATUS.OK,
    message,
    data: items,
    meta,
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建统计响应
 * @param {Object} stats - 统计数据
 * @param {string} message - 响应消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function stats(stats, message = "Statistics retrieved successfully", requestId = null) {
  return {
    code: HTTP_STATUS.OK,
    message,
    data: stats,
    meta: {
      type: 'statistics'
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建错误响应
 * @param {string|number} codeOrName - 错误码或错误名称
 * @param {string} customMessage - 自定义错误消息
 * @param {Object} details - 错误详情
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function error(codeOrName, customMessage = null, details = null, requestId = null) {
  const errorInfo = createError(codeOrName, customMessage, details);

  return {
    code: errorInfo.code,
    message: errorInfo.message,
    data: null,
    meta: {
      error: {
        description: errorInfo.description,
        details: errorInfo.details,
        type: getErrorType(errorInfo.code)
      }
    },
    timestamp: errorInfo.timestamp,
    requestId
  };
}

/**
 * 创建验证错误响应
 * @param {Object} validationErrors - 验证错误详情
 * @param {string} message - 错误消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function validationError(validationErrors, message = "Validation failed", requestId = null) {
  return {
    code: 12000, // VALIDATION_ERROR
    message,
    data: null,
    meta: {
      error: {
        description: "Input data validation failed",
        details: validationErrors,
        type: 'validation'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建未找到资源响应
 * @param {string} resource - 资源名称
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function notFound(resource = "Resource", requestId = null) {
  return {
    code: 13000, // RESOURCE_NOT_FOUND
    message: `${resource} not found`,
    data: null,
    meta: {
      error: {
        description: `The requested ${resource.toLowerCase()} was not found`,
        details: null,
        type: 'resource'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建未授权响应
 * @param {string} message - 错误消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function unauthorized(message = "Authentication required", requestId = null) {
  return {
    code: 11000, // AUTHENTICATION_REQUIRED
    message,
    data: null,
    meta: {
      error: {
        description: "Authentication is required to access this resource",
        details: null,
        type: 'auth'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建禁止访问响应
 * @param {string} message - 错误消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function forbidden(message = "Permission denied", requestId = null) {
  return {
    code: 11004, // PERMISSION_DENIED
    message,
    data: null,
    meta: {
      error: {
        description: "You don't have permission to access this resource",
        details: null,
        type: 'auth'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建冲突响应
 * @param {string} message - 错误消息
 * @param {Object} details - 冲突详情
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function conflict(message = "Resource already exists", details = null, requestId = null) {
  return {
    code: 13001, // RESOURCE_ALREADY_EXISTS
    message,
    data: null,
    meta: {
      error: {
        description: "A resource with the same identifier already exists",
        details,
        type: 'resource'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建服务器错误响应
 * @param {string} message - 错误消息
 * @param {Object} details - 错误详情
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function serverError(message = "Internal server error", details = null, requestId = null) {
  return {
    code: 10000, // UNKNOWN_ERROR
    message,
    data: null,
    meta: {
      error: {
        description: "An unexpected error occurred in the system",
        details,
        type: 'system'
      }
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 获取错误类型
 * @param {number} code - 错误码
 * @returns {string} 错误类型
 */
function getErrorType(code) {
  if (code >= 11000 && code < 12000) return 'auth';
  if (code >= 12000 && code < 13000) return 'validation';
  if (code >= 13000 && code < 14000) return 'resource';
  if (code >= 14000 && code < 17000) return 'business';
  if (code >= 17000 && code < 18000) return 'file';
  if (code >= 18000 && code < 19000) return 'database';
  if (code >= 19000 && code < 20000) return 'external';
  return 'system';
}

/**
 * 包装Moleculer服务方法的响应
 * @param {Function} serviceMethod - 服务方法
 * @param {Object} ctx - Moleculer上下文
 * @returns {Function} 包装后的方法
 */
function wrapServiceMethod(serviceMethod) {
  return async function(ctx) {
    try {
      const result = await serviceMethod.call(this, ctx, { meta: { $cache: false } });

      // 如果结果已经是标准响应格式，直接返回
      if (result && typeof result === 'object' &&
          'code' in result && 'message' in result && 'timestamp' in result) {
        return result;
      }

      // 否则包装为成功响应
      return success(result, "Success", null, ctx.requestID);
    } catch (err) {
      // 如果是Moleculer错误且包含错误码
      if (err.code && err.code >= 10000) {
        return error(err.code, err.message, err.data, ctx.requestID);
      }

      // 默认服务器错误
      return serverError(err.message, null, ctx.requestID);
    }
  };
}

/**
 * 格式化数据库查询结果为列表响应
 * @param {Array} items - 查询结果
 * @param {Object} query - 查询参数
 * @param {number} total - 总数量
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function formatQueryResult(items, query = {}, total = null, requestId = null) {
  const { page, pageSize } = query;

  // 如果有分页参数，返回分页响应
  if (page && pageSize) {
    const totalCount = total !== null ? total : items.length;
    return paginated(items, page, pageSize, totalCount, "Success", requestId);
  }

  // 否则返回列表响应
  return list(items, total, "Success", requestId);
}

/**
 * 处理文件上传响应
 * @param {Object} fileInfo - 文件信息
 * @param {string} message - 响应消息
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function fileUploaded(fileInfo, message = "File uploaded successfully", requestId = null) {
  return {
    code: HTTP_STATUS.CREATED,
    message,
    data: {
      filename: fileInfo.filename,
      originalName: fileInfo.originalname,
      size: fileInfo.size,
      mimeType: fileInfo.mimetype,
      url: fileInfo.url || `/uploads/${fileInfo.filename}`,
      uploadedAt: new Date().toISOString()
    },
    meta: {
      type: 'file_upload'
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

/**
 * 创建批量操作响应
 * @param {Object} result - 批量操作结果
 * @param {string} operation - 操作类型
 * @param {string} requestId - 请求ID
 * @returns {StandardResponse} 标准响应对象
 */
function batchOperation(result, operation = "batch", requestId = null) {
  const { success: successCount = 0, failed: failedCount = 0, errors = [] } = result;
  const total = successCount + failedCount;

  return {
    code: HTTP_STATUS.OK,
    message: `Batch ${operation} completed`,
    data: {
      total,
      success: successCount,
      failed: failedCount,
      errors: errors.length > 0 ? errors : null
    },
    meta: {
      type: 'batch_operation',
      operation
    },
    timestamp: new Date().toISOString(),
    requestId
  };
}

module.exports = {
  success,
  created,
  updated,
  deleted,
  paginated,
  list,
  stats,
  error,
  validationError,
  notFound,
  unauthorized,
  forbidden,
  conflict,
  serverError,
  wrapServiceMethod,
  formatQueryResult,
  fileUploaded,
  batchOperation
};